package finalVersion;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder; //import test.Connection;

import javax.swing.border.EtchedBorder;
import java.awt.Color;
import java.util.*;

public class ServerGUI extends JFrame implements ActionListener {

	// GUI
	private JTextArea connectionDetail;
	private JList list;
	private JTextField serverPort;
	private JLabel serverStatus;
	private JButton btnListen;

	// Server
	private ServerSocket serverSocket = null;
	private Socket communicationSocket = null;
	private List<Connection> connections = null;
	public List<String> userOnline = null;

	public Map<String, Connection> userIDtoConnection = null;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					ServerGUI frame = new ServerGUI();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	//Code Genereted by Swing designer
	public ServerGUI() {
		setTitle("Server");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 513, 300);
		getContentPane().setLayout(new BorderLayout(0, 0));

		JPanel panel = new JPanel();
		getContentPane().add(panel, BorderLayout.EAST);
		panel.setLayout(new BorderLayout(0, 0));

		JScrollPane panel_3 = new JScrollPane();
		panel_3.setViewportBorder(new TitledBorder(new EtchedBorder(
				EtchedBorder.LOWERED, null, null), "User Online",
				TitledBorder.LEADING, TitledBorder.TOP, null,
				new Color(0, 0, 0)));
		panel.add(panel_3, BorderLayout.CENTER);

		list = new JList();
		list.setFixedCellWidth(200);
		list.setEnabled(true);
		panel_3.setViewportView(list);

		JPanel panel_2 = new JPanel();
		panel_2.setBorder(new TitledBorder(new EtchedBorder(
				EtchedBorder.LOWERED, null, null), "Listen",
				TitledBorder.LEADING, TitledBorder.TOP, null,
				new Color(0, 0, 0)));
		panel_3.setColumnHeaderView(panel_2);
		panel_2.setLayout(new BorderLayout(0, 0));

		JLabel lblPort = new JLabel("Port  ");
		panel_2.add(lblPort, BorderLayout.WEST);

		serverPort = new JTextField();
		panel_2.add(serverPort, BorderLayout.CENTER);
		serverPort.setColumns(10);

		btnListen = new JButton("Listen");
		panel_2.add(btnListen, BorderLayout.EAST);
		btnListen.addActionListener(this);

		serverStatus = new JLabel("Status: Not Listening");
		panel_2.add(serverStatus, BorderLayout.SOUTH);

		JScrollPane panel_1 = new JScrollPane();
		panel_1.setViewportBorder(new TitledBorder(new EtchedBorder(
				EtchedBorder.LOWERED, null, null), "Connection Detail",
				TitledBorder.LEADING, TitledBorder.TOP, null,
				new Color(0, 0, 0)));
		getContentPane().add(panel_1, BorderLayout.CENTER);

		connectionDetail = new JTextArea();
		connectionDetail.setEditable(false);
		panel_1.setViewportView(connectionDetail);
	}

	synchronized void closeConnection(Connection connection, String userID) {
		connections.remove(connection);
		userOnline.remove(userID);
	}
	
	
	public void addUser(String UserID, Connection con) {
		if (userOnline != null) {
			userOnline.add(UserID);
		}
		userIDtoConnection.put(UserID, con);

		StringBuffer update = new StringBuffer("Update");
		for (String s : userOnline) {
			update.append(":" + s);
		}
		sendToAllClients(update.toString());

	}

	@Override
	public void actionPerformed(ActionEvent event) {

		try {
			System.out.println("Attempting to start server...");
			serverSocket = new ServerSocket(Integer.parseInt(serverPort
					.getText()));
			serverStatus.setText("Listening on port " + serverPort.getText());
		} catch (Exception ex) {
			ex.printStackTrace();
			serverStatus.setText("Status: Cannot Listening on port "
					+ serverPort.getText());
		}
		runServer();

	}
	
	//notify the server if a new user connect
	public void setDetailConnection(String s) {
		connectionDetail.append(s + "\n");
	}

	public void sendToAllClients(String message) {
		for (Connection c : connections) {
			c.sendMessage(message);
		}
	}
	
	//Start server
	private void runServer() {
		userOnline = new ArrayList<String>();
		connections = new ArrayList<Connection>();
		userIDtoConnection = new HashMap<String, Connection>(50);
		Thread serverThread = new Thread(new processRequest());
		serverThread.start();
		Thread Refresh = new Thread(new refreshUserList());
		Refresh.start();
	}

	private class processRequest implements Runnable {
		@Override
		public void run() {
			while (true) {
				try {
					// Wait here and listen for a connection
					communicationSocket = serverSocket.accept();
					handleConnection(communicationSocket);
					System.out.println(connections.size());
					System.out.println("number user:" + userOnline.size());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

		}

	}

	//A Thread run permanently to display a new user connect to server
	private class refreshUserList implements Runnable {
		public void run() {
			while (true) {
				String display = "";
				for (String s : userOnline) {
					if (display.equals("")) {
						display = s;
					} else {
						display = display + ":" + s;
					}
				}
				String[] spl = display.split(":");
				list.setListData(spl);
			}
		}
	}

	private synchronized void handleConnection(Socket clientSocket) {
		Connection con = new Connection(this, clientSocket);
		Thread t = new Thread(con);
		t.start();
		connections.add(con);
	}
}
